package com.guochu.common.aspect;

import com.guochu.common.annotation.CloseAuth;
import com.guochu.common.AuthService;
import com.guochu.common.ResultMap;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @author luc
 * 判断当前是否是匿名用户，匿名用户需要提示登录
 * 记录调用日志
 */
@Aspect
@Component
public class AuthAspect {

    private static final Logger logger = LoggerFactory.getLogger(AuthAspect.class);

    @Autowired
    AuthService authService;

    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    @Order(10000)
    public void logPointCut() {
    }

    @Before("logPointCut()")
    public void doBefore(JoinPoint joinPoint) {
        // 接收到请求，记录请求内容
        //ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //HttpServletRequest request = attributes.getRequest();

        // 记录下请求内容
        //logger.info("方法 : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        //logger.info("参数 : " + Arrays.toString(joinPoint.getArgs()));
    }

    @AfterReturning(returning = "ret", pointcut = "logPointCut()")
    public void doAfterReturning(Object ret) throws Throwable {
        //logger.debug("返回 : " + ret);
    }

    /**
     * 身份验证--开始
     *
     * <p>终端每次请求API接口必须经过此方法的身份过滤
     * 终端的请求头必须包含 token、timestamp、sign
     *
     * <p>此方法获取用户的请求头信息
     *
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("logPointCut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        MethodSignature signature = (MethodSignature) pjp.getSignature();
        //是否需要认证
        CloseAuth cloAuth = signature.getMethod().getAnnotation(CloseAuth.class);

        //开发中不需要登录
        if (cloAuth == null || !cloAuth.value()) {
//        if(false){
            String token = request.getHeader("token");
            String timestamp = request.getHeader("timestamp");
            String sign = request.getHeader("sign");

            if (token == null || "null".equals(token) || "".equals(token) || !authService.checkToken(token, timestamp, sign)) {
                return ResultMap.error("A0220","用户身份校验失败").put("code", 401);
            }
        }

        //判断接口权限

        //判断接口参数

        try {

//            //开始时间
//            Instant instantStart = Instant.now();
//
//            // ob 为方法的返回值，执行这句，然后执行before，然后执行控制器，然后执行下面的语句。
//            Object rtn = pjp.proceed();
//
//            //结束时间
//            Instant instantEnd = Instant.now();
//
//            Long duration = Duration.between(instantStart, instantEnd).toMillis();
//
//            if (duration > 1000) {
//                //todo; 大于1s记录日志，后期改为配置
//                Log log = new Log(2, request.getRemoteAddr(), request.getRemoteHost(), request.getRequestURI(), duration, "");
//                logService.insert(log);
//            }

            return pjp.proceed();
        } catch (Exception ex) {
            //记录本地日志
            logger.error(request.getRequestURI(), ex);

            //记录服务器日志
//            Log log = new Log(2, request.getRemoteAddr(), request.getRemoteHost(), request.getRequestURI(), 0L, ex.getMessage());
//            logService.insert(log);

            return ResultMap.error(ex.getMessage());
        }
    }
}
